package org.brisling.base.service;

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import javax.persistence.Entity;
import javax.persistence.EntityManager;
import javax.persistence.Query;
import javax.persistence.Table;

import org.brisling.common.ConstSysParam;
import org.brisling.common.util.LongUtil;
import org.brisling.common.util.MapUtil;
import org.brisling.common.util.ReflectDataUtil;
import org.hibernate.SQLQuery;
import org.hibernate.transform.Transformers;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.web.servlet.ModelAndView;

public abstract class AbstractBaseService {
	
	private static Logger logger = LoggerFactory.getLogger(AbstractBaseService.class);
	
	private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
	protected void setEntityManager(EntityManager entityManager){
		this.entityManager = entityManager;		
	}
	protected EntityManager entityManager;	
	//定义起始页是否为1
	protected Boolean pageBasedOne=false;
	
	protected String moduleName = null;
	
	protected String subSystem = null;
	
	protected String mainPage = "main";
	
	protected String editPage = "editDlg";
	
	//默认排序字段
	protected Sort defaultSort= new Sort(new String[] { "sortedid" });
		
	protected HashMap<String,Method>  methodMap = new HashMap<String,Method>();

	
	
	public String getModuleName() {
		return moduleName;
	}


	public EntityManager getEntityManager(){
		return this.entityManager;
	}
	
	
	/**
	 * 获取业务主页面 
	 * @return
	 */
	
	protected ModelAndView getBizMainPage(){
		System.out.println("subSystem,moduleName,mainPage"+subSystem+","+moduleName+","+mainPage);
		String _page = String.format("/%1$s/%2$s/%3$s", subSystem,moduleName,mainPage);
		return new ModelAndView(_page);		
	}
	
	
	/**
	 * 业务编号自动生成函数
	 * @return
	 */	
	public String generateBizno(){
		
		Date date = new Date();
		return this.generateBizno(date);
		
	}
	
	/**
	 * 业务编号自动生成函数
	 * @return
	 */
	@SuppressWarnings("rawtypes")
	public String generateBizno(Date _date){
		
		
		Date date = _date==null?new Date():_date;
		SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd");
		String datStr = format.format(date);
		String whereCorse = String.format(" where bizno like '%1$s%%'",datStr);
		String sql = String.format("select max(bizno) as \"bizno\" from %1$s %2$s",this.moduleName,whereCorse);
		
		
		Query qry = entityManager.createNativeQuery(sql);
		HashMap map =this.getSingalQueryResult(qry);
		if(map!=null && map.containsKey("bizno")){
			Object obj = map.get("bizno");
			if(obj!=null){
				Long _no = LongUtil.getLongValue(obj.toString(),null);
				if(_no!=null){
					_no +=1;
					return _no.toString();
				}else{
					return obj.toString();
				}
				
			}else{
				return  datStr+"001";
			}
			
		}else{		
			return  datStr+"001";
		}
	}
	
	/**
	 * 单个对象查询
	 * @param query
	 * @return
	 */
	@SuppressWarnings("rawtypes")
	protected HashMap getSingalQueryResult(Query query){
		
		query.unwrap(SQLQuery.class).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
		HashMap obj;
		try{
			obj = (HashMap) query.getSingleResult();
		}catch(Exception e){
			logger.error("no result found for query ...");
			//e.printStackTrace();
			obj = new HashMap();
		}
		 
		return obj;
	}	
	protected ModelAndView getBizEditPage(){
		
		String _page = String.format("/%1$s/%2$s/%3$s", subSystem,moduleName,editPage);
		return new ModelAndView(_page);
	}
	
	protected ModelAndView getBizPage(String subName,String moduName,String pageName){
		
		String _subName = subName==null?subSystem:subName;
		String _moduName = moduName==null?moduleName:moduName;
		String _pageName = pageName==null?mainPage:pageName;
		String _page = String.format("/%1$s/%2$s/%3$s", _subName,_moduName,_pageName);
		return new ModelAndView(_page);
	}
	
	/**
	 * 根据页号和每页行数获取起始记录数
	 * @param page	页号
	 * @param rows	每页行数
	 * @return
	 */
	protected Integer[] getPageParam(String page,String rows){
		int _page = LongUtil.getIntValue(page, ConstSysParam.PAGE);
		int _rows = LongUtil.getIntValue(rows, ConstSysParam.ROWS);
		return this.getPageParam(_page, _rows);
	}
	
	/**
	 * 根据页号和每页行数获取起始记录数
	 * @param page	页号
	 * @param rows	每页行数
	 * @return
	 */
	protected Integer[] getPageParam(Integer page,Integer rows){
		Integer[] intArr = new Integer[2];
		int _page = (page==null)||(page==0)?ConstSysParam.PAGE:page.intValue()-1;
		int _rows = rows==null?ConstSysParam.ROWS:rows.intValue();
		intArr[0] = _page *_rows ;
		intArr[1] =  _rows ;
		return intArr;
	}
	
	/*
	 * 初始化对象实体方法反射结果集
	 */
	protected void initMethodMap(Class<?> target){
		
		Method[] methods = target.getMethods();
		for(int i=0;i<methods.length;i++){
			methodMap.put(methods[i].getName(), methods[i]);
		}
		
		methods = target.getDeclaredMethods();
		for(int i=0;i<methods.length;i++){
			methodMap.put(methods[i].getName(), methods[i]);
		}
	}
	
	/*
	 * 根据字段名称查找对象实体中字段类型
	 */
	protected Class<?> getFieldClass(String fieldName,Class<?> target){
		
		String methodName = "get"+fieldName.substring(0,1).toUpperCase()+fieldName.substring(1);
		
		if((methodMap==null)||(methodMap.size()<=0))
				initMethodMap(target);
		
		Method method = methodMap.get(methodName);
		if(method!=null){
			System.out.println("method " + methodName + " matched ..." );
			return method.getReturnType();
		}else
			return null;
	}
	
	/**
	 * 分页条件组装函数
	 * @param page	页号
	 * @param pageSize	每页行数
	 * @param sort	排序条件
	 * @return	PageRequest spring分页查询条件
	 */
	protected PageRequest getPageRequest(String page,String pageSize,Sort sort){
		Integer _page = LongUtil.getIntValue(page, null);
		Integer _size = LongUtil.getIntValue(pageSize, null);		
		return this.getPageRequest(_page, _size, sort);
	}
	
	/**
	 * 分页条件组装函数
	 * @param page	页号
	 * @param pageSize	每页行数
	 * @param sort	排序字段
	 * @return	PageRequest spring分页查询条件
	 */
	protected PageRequest getPageRequest(Integer page,Integer pageSize,String sort){		
		
		Sort _sort = sort==null? defaultSort :new Sort(new String[]{sort}) ;
		
		return this.getPageRequest(page, pageSize, _sort);
	}
	/**
	 * 分页条件组装函数
	 * @param page	页号
	 * @param pageSize	每页行数
	 * @param sort	排序条件
	 * @return	PageRequest spring分页查询条件
	 */
	
	protected PageRequest getPageRequest(Integer page,Integer pageSize,Sort sort){
		PageRequest _pageRequest = null;
		
		page=(page==null)||(page<=0)?ConstSysParam.PAGE:page-1;
		pageSize=pageSize==null?ConstSysParam.ROWS:pageSize;
		
			Sort _sort = sort==null? new Sort(new String[] {"sortedid" }) :sort ;
			_pageRequest= new PageRequest(page,pageSize,_sort );
		
		return _pageRequest;
	}
	
	/**
	 * 获取实体类定义的表名称
	 * @param clazz
	 * @return
	 */
	protected String getTableName(Class<?> clazz){
		Entity entity = clazz.getAnnotation(Entity.class);
		if(entity.name().trim().compareTo("")!=0){
			return entity.name();
		}
		Table table = clazz.getAnnotation(Table.class);		
		return table.name();		
	}
	
	/**
	 * 获取实体类定义的字段名称及类型map
	 * @param clazz
	 * @return
	 */
	protected HashMap<String,String> getTypeMap(Class<?> clazz){
		HashMap<String,String> maps = new HashMap<String,String>();
		if(clazz!=null){
			maps = ReflectDataUtil.getParentClassFields(maps,clazz);
		}
		
		return maps;		
	}
	
	
	
	@SuppressWarnings("rawtypes")  
    public Object convertMap(Class type, Map map)  
            throws IntrospectionException, IllegalAccessException,  
            InstantiationException, InvocationTargetException {  
        BeanInfo beanInfo = Introspector.getBeanInfo(type); // 获取类属性  
        Object obj = type.newInstance(); // 创建 JavaBean 对象  
  
        // 给 JavaBean 对象的属性赋值  
        PropertyDescriptor[] propertyDescriptors =  beanInfo.getPropertyDescriptors();  
        for (int i = 0; i< propertyDescriptors.length; i++) {  
            PropertyDescriptor descriptor = propertyDescriptors[i];  
            String propertyName = descriptor.getName();  
  
            if (map.containsKey(propertyName)) {  
                // 下面一句可以 try 起来，这样当一个属性赋值失败的时候就不会影响其他属性赋值。  
            	Method method = null;
            	try{
                Object value = map.get(propertyName);  
  
                Object[] args = new Object[1];  
                args[0] = value;  
                method = descriptor.getWriteMethod();
                method.invoke(obj, args);  
            	}catch(Exception e){
            		System.out.println("Method: " + method.getName());
            		e.printStackTrace();
            	}
            }  
        }  
        return obj;  
    }
	
	protected String encodeStr(String str){
		
			try {
				return new String(str.getBytes("ISO-8859-1"),"UTF-8");
			} catch (UnsupportedEncodingException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				return null;
			}
		
	}
	
	/**
	 * 根据前端参数获取查询条件map
	 * @param body request 参数
	 * @return Map 名值对
	 */
	
	protected Map<String,Object> getBodyParam(String body){
		return MapUtil.getBodyParam(body);
	}
	
	
	
	
	
	
	
	/**
	 * 生成条件查询语句
	 * @param map
	 * @param t
	 * @return
	 */
	@SuppressWarnings({ "rawtypes" })
	protected String getConditionStr(Map<String,String> map,Class<?> t){
		
		String retStr = "";
		if(map!=null && !map.isEmpty()){
			Object clazz =null;
			try {
				clazz =  t.newInstance();
			} catch (InstantiationException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
			for(Map.Entry<String, String> entry:map.entrySet()){
				Class _fieldClass = ReflectDataUtil.getDeclaredFieldClass(entry.getKey(), clazz);
				if(_fieldClass!=null){
					String str = _fieldClass.getName();
					
					String numberTemplate = " %1$s = %2$s";
					String strTemplate = " %1$s = '%2$s'";
					String dateTemplate = " %1$s = to_date( %2$s ,'yyyy-mm-dd hh24:mi:ss')";
					if(str!=null){
						String _tmpStr =null;
						switch(str){
						case "java.lang.Integer"
							:_tmpStr = String.format(numberTemplate,entry.getKey() ,entry.getValue());
							break;
						case "java.lang.Long"	
							:_tmpStr = String.format(numberTemplate,entry.getKey() ,entry.getValue());
							break;
						case "java.lang.String"
							:_tmpStr = String.format(strTemplate,entry.getKey() ,entry.getValue());
							break;
						case "java.util.Date"
							:_tmpStr = String.format(dateTemplate,entry.getKey() ,entry.getValue());
						default:
							_tmpStr=null;
						};
						
						retStr=retStr.compareTo("")==0?(retStr+_tmpStr):(retStr += " AND " +_tmpStr);
					}else{
						System.out.println("field: "+entry.getKey() + " not found on " +clazz.getClass());
					}
				}
			}
		}
		
		
		return retStr;
		
	}
	
	/**
	 * 获取动态查询排序条件
	 * @param sort
	 * @return
	 */
	protected String getOrderStr(Map<String,String> sort){
		
		String retStr = null;
		if((sort!=null)&&(!sort.isEmpty())){
			
			String _tmpStr = null;
			for(Map.Entry<String, String> entry:sort.entrySet()){
				String sortKey = entry.getKey();
				String sortValue = entry.getValue();
				if(sortKey!=null){
					if((sortValue==null)||(sortValue.trim().length()<=0)||(sortValue.toUpperCase().compareTo("ASC")==0)){				
						_tmpStr=sortKey + " ASC ";	
					}else{
						_tmpStr=sortKey + " DESC ";
					}
				}
				
				if(_tmpStr!=null){				
					retStr=retStr==null?_tmpStr:(retStr + "," +_tmpStr);
				}
			}			
		}
		
		return retStr;
	}
	protected Date jsonStr2Date(String _date){
		
		
		if(_date ==null || _date.trim().compareTo("")==0){
			return null;
		}else{
			_date = _date.trim();
		}
		
		Date retDate = null;
		String _tmpDate = null;
		if(_date!=null){
			Integer _dateLength = _date.length();
			if(_date.length()>19)
				_tmpDate = _date.substring(0,19);
			else{
				switch(_dateLength){
				case 10
					:_tmpDate =_date + " 00:00:00";
					break;
				case 13
					:_tmpDate= _date + ":00:00";
					break;
				case 16
					:_tmpDate =  _date = ":00";
					break;
				default
					:break;
			}
			}
		}
		
		
		try{
			
			retDate = sdf.parse(_tmpDate);
		}catch(NumberFormatException | ParseException  e){
//			e.printStackTrace();
			System.out.println("_sdf _date:" + _tmpDate.toString());
			System.out.println("exception occured ");
		}
		return retDate;
	}
	
}
